package db;


import java.lang.ref.WeakReference;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import org.apache.log4j.Logger;
import org.hibernate.Session;

public class TxHandle {
  private static Logger                     LOG         = Logger.getLogger( TxHandle.class );

  private EntityManager     em;
  private EntityTransaction etx;
  private EntityManagerFactory anemf;
  private WeakReference<Session>           session;
  //private static String PersistenceUnit = "MEMC2";

  public TxHandle( String ctx ) {
   
	  anemf = Persistence.createEntityManagerFactory(ctx);
    try {
      this.em = anemf.createEntityManager( );
      this.etx = em.getTransaction( );
      this.etx.begin( );
      this.session = new WeakReference<Session>(( Session ) em.getDelegate( ));
      
    } catch ( Throwable e ) {
      this.rollback( );
      LOG.error( e, e );
      throw new RuntimeException( e );
    }
  }

  public void rollback( ) {
	  if( this.session != null ) {
	      this.session.clear( );        
	    }
    try {
      if ( this.etx != null && this.etx.isActive( ) ) {
        this.etx.rollback( );
      }
    } catch( Throwable e ) {
      LOG.error( e, e );
    } finally {
      this.etx = null;
      
      if( this.em != null ) {
        this.em.close( );
      }
      this.em = null;
    }
  }

  public void commit( ) {
	  if( this.session != null ) {
	      this.session.clear( );
	    }
    try {
      this.etx.commit( );
    } catch( RuntimeException e ) {
      if( this.etx != null && this.etx.isActive( ) ) {
        this.etx.rollback( );
        LOG.debug( e, e );
        throw e;
      }
    } finally {
      this.etx = null;
      if( this.em != null ) {
        this.em.close( );
      }
      
      if( this.anemf != null ) {
          this.anemf.close( );
      }
      
      this.em = null;
    }
  }
  
  public Session getSession( ) {
	    if( session.get( ) == null ) {
	      RuntimeException e = new RuntimeException( "Someone is calling a closed tx handle: ");
	      LOG.error( e, e );
	      throw e;
	    }
	    return session.get( );
	  }
  
  public boolean getRollbackOnly( ) {
    return etx.getRollbackOnly( );
  }

  public boolean isActive( ) {
    return etx.isActive( );
  }

  public void setRollbackOnly( ) {
	  etx.setRollbackOnly( );
  }

  public EntityManager getEntityManager( ) {
    return this.em;
  }

  public void begin( ) {
	  etx.begin( );
  }



}

